package com.why.rpc.core.common.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import lombok.extern.slf4j.Slf4j;
import com.why.rpc.core.common.enums.ErrorEnum;
import com.why.rpc.core.common.enums.PackageType;
import com.why.rpc.core.common.exception.RpcException;
import com.why.rpc.core.common.message.RpcRequest;
import com.why.rpc.core.common.message.RpcResponse;
import com.why.rpc.core.common.serializable.CommonSerializable;

import java.util.List;

/**
 * @program: whyrpcframework
 * @description:
 * @author: @why
 * @create: 2021-03-11 22:50
 **/
@Slf4j
public class CommonDecoder extends ReplayingDecoder {
    private static final int MAGIC_NUMBER = 0xCAFEBABE;

    /**
     * +---------------+---------------+-----------------+-------------+
     * |  Magic Number |  Package Type | Serializer Type | Data Length |
     * |    4 bytes    |    4 bytes    |     1 bytes     |   4 bytes   |
     * +---------------+---------------+-----------------+-------------+
     * |                          Data Bytes                           |
     * |                   Length: ${Data Length}                      |
     * +---------------------------------------------------------------+
     * ————————————————
     *
     * @param ctx
     * @param in
     * @param out
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        System.out.println("开始解密");


        //挨个读，我们的解码协议 先是读取魔法数字，再读取包类型，再读取序列化类型，再读取长度
        int magic = in.readInt();
        if (magic != MAGIC_NUMBER) {
            log.error("不识别的协议包{}", magic);
            throw new RpcException(ErrorEnum.ILLEGAL_TYPE_ERROR);
        }
        //1.当前的请求类型
        Class<?> packageClass;
        int packageCode = in.readInt();
        log.info("获取到packageCode:{}", packageCode);
        //2.判断是什么包类型
        if (packageCode == PackageType.REQUEST_PACK.getCode()) {
            packageClass = RpcRequest.class;
        } else if (packageCode == PackageType.RESPONSE_PACK.getCode()) {
            packageClass = RpcResponse.class;
        } else {
            log.warn("无法处理的数据包");
            throw new RpcException(ErrorEnum.PACKAGE_TYPE_ERROR);

        }
        int serializerCode =  in.readInt();
        System.out.println("序列化码"+serializerCode);
        CommonSerializable commonSerializable = CommonSerializable.getByCode(serializerCode);
        if (commonSerializable == null) {
            log.error("不识别的反序列化器: {}", serializerCode);
            throw new RpcException(ErrorEnum.NOT_FOUNT_SERIALIZER_TYPE_ERROR);
        }

        //3.获取数据的长度，4字节。
        int length = in.readInt();
        byte[] data = new byte[length];
        //4.将得到的对象变为字节流放入字节数组
        in.readBytes(data);
        //完成反序列化,放入通道
        Object deserialize = commonSerializable.deserialize(data, packageClass);
        out.add(deserialize);


    }
}
